package com.immortal.core.autoconfigure;

import com.immortal.core.configure.CorsConfig;
import com.immortal.core.filters.HttpTraceLogFilter;
import com.immortal.core.filters.HttpTraceLogService;
import com.immortal.core.service.I18nService;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.micrometer.core.instrument.MeterRegistry;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.persistence.EntityManager;
import java.util.Arrays;

/**
 * <p>TODO
 *
 * @author wind
 * @version 1.0
 * @since 2018/12/12
 */
@Configuration
public class ImAutoConfiguration {

    @ConditionalOnClass(JPAQueryFactory.class)
    @Bean
    public JPAQueryFactory jpaQuery(EntityManager entityManager) {
        return new JPAQueryFactory(entityManager);
    }

    @Autowired
    private MessageSource messageSource;

    @Bean
    public I18nService i18nService() {
        return new I18nService(messageSource);
    }

    @ConditionalOnProperty(
            prefix = "spring.mvc.filter.httpTrace",
            name = {"enabled"},
            havingValue = "true"
    )
    @Bean
    public FilterRegistrationBean testFilterRegistration(@Value("${spring.mvc.filter.httpTrace.name:}") String name,
                                                         @Value("#{'${spring.mvc.filter.httpTrace.allow:}'.split(',')}") String[] allowPath,
                                                         @Value("#{'${spring.mvc.filter.httpTrace.expose:}'.split(',')}") String[] exposePath,
                                                         @Value("${spring.mvc.filter.httpTrace.order:}") Integer order,
                                                         MeterRegistry meterRegistry, ObjectProvider<HttpTraceLogService> traceLogService) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        HttpTraceLogFilter httpTraceLogFilter = new HttpTraceLogFilter(meterRegistry);
        if (traceLogService.getIfAvailable() != null) {
            httpTraceLogFilter.setTraceLogService(traceLogService.getIfAvailable());
        }
        httpTraceLogFilter.addExposePatterns(exposePath);
        httpTraceLogFilter.addAllowPatterns(allowPath);
        registration.setFilter(httpTraceLogFilter);
        //String[] pp = (StringUtils.hasText(path[0])) ? path : new String[]{"/*"};
        if (StringUtils.hasText(name)) {
            registration.setName(name);
        }
        registration.addUrlPatterns("/*");
        registration.setOrder(order == null ? Ordered.LOWEST_PRECEDENCE - 10 : order);
        return registration;
    }

    @ConditionalOnBean(CorsConfig.class)
    @Bean
    public WebMvcConfigurer corsConfigurer(ObjectProvider<CorsConfig> corsConfigObjectProvider) {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                CorsConfig corsConfig = corsConfigObjectProvider.getIfAvailable();
                if (corsConfig != null) {
                    if (corsConfig.getDetail() != null) {
                        corsConfig.getDetail().forEach(v ->
                                registry.addMapping(v.getPath())
                                        .allowedOrigins(v.getAllowedOrigins())
                                        .allowedHeaders((v.getAllowedHeaders()))
                                        .allowedMethods(v.getAllowedMethods())
                                        .allowCredentials(v.getAllowCredentials())
                        );
                    }

                }

            }
        };
    }

    @Value("${spring.dozer.basename:}")
    private String dozerBaseName;
    @Bean
    public DozerBeanMapper mapper() {
        DozerBeanMapper mapper = new DozerBeanMapper();
        mapper.setMappingFiles(Arrays.asList(dozerBaseName));
        return mapper;
    }


}
